library(sf) # classes and functions for vector data
Linking to GEOS 3.8.0, GDAL 3.0.4, PROJ 6.3.1; sf_use_s2() is TRUE
library(spData) # load geographic data
To access larger datasets in this package, install the spDataLarge package with: `install.packages('spDataLarge', repos='https://nowosad.github.io/drat/', type='source')`
library(dplyr)
Attaching package: ‘dplyr’
The following objects are masked from ‘package:stats’:
filter, lag
The following objects are masked from ‘package:base’:
intersect, setdiff, setequal, union
library(tmap) # for static and interactive maps
Registered S3 method overwritten by 'htmlwidgets':
method from
print.htmlwidget tools:rstudio
library(ggplot2)
library(ggsci)
library(tools)
library(readr)
library(foreach)
library(doParallel)
Loading required package: iterators
Loading required package: parallel
registerDoParallel(detectCores())
getDoParWorkers()
[1] 96
load("data/ca.data.RData")
dem=tm_shape(ca.data) +tm_fill(col = "dist",palette = "viridis",legend.show=FALSE,alpha=0.4)+
tm_dots(size = "party_dem",col="blue",alpha=0.5,legend.show=FALSE)+
tm_layout(title = "California", frame = FALSE, bg.color = NA)
rep=tm_shape(ca.data) +tm_fill(col = "dist",palette = "viridis",legend.show=FALSE,alpha=0.4)+
tm_dots(size = "party_rep",col="red",alpha=0.5,legend.show=FALSE)+
tm_layout(title = "California", frame = FALSE, bg.color = NA)
black=tm_shape(ca.data) +tm_fill(col = "dist",palette = "viridis",legend.show=FALSE,alpha=0.4)+
tm_dots(size = "eth1_aa",col="black",alpha=0.5,legend.show=FALSE)+
tm_layout(title = "California", frame = FALSE, bg.color = NA)
white=tm_shape(ca.data) +tm_fill(col = "dist",palette = "viridis",legend.show=FALSE,alpha=0.4)+
tm_dots(size = "eth1_eur",col="yellow",alpha=0.5,legend.show=FALSE)+
tm_layout(title = "California", frame = FALSE, bg.color = NA)
hisp=tm_shape(ca.data) +tm_fill(col = "dist",palette = "viridis",legend.show=FALSE,alpha=0.4)+tm_dots(size = "eth1_hisp",col="brown",alpha=0.5,legend.show=FALSE)+tm_layout(title = "California", frame = FALSE, bg.color = NA)
asian=tm_shape(ca.data) +tm_fill(col = "dist",palette = "viridis",legend.show=FALSE,alpha=0.4)+tm_dots(size = "eth1_esa",col="orange",alpha=0.5,legend.show=FALSE)+tm_layout(title = "California", frame = FALSE, bg.color = NA)
tmap_arrange(black,white,hisp,asian,dem,rep,nrow = 2,ncol=4)

load("data/tx.data.RData")
dem=tm_shape(tx.data) +tm_fill(col = "dist",palette = "viridis",legend.show=FALSE,alpha=0.4)+
tm_dots(size = "party_dem",col="blue",alpha=0.5,legend.show=FALSE)+
tm_layout(title = "Texas", frame = FALSE, bg.color = NA)
rep=tm_shape(tx.data) +tm_fill(col = "dist",palette = "viridis",legend.show=FALSE,alpha=0.4)+
tm_dots(size = "party_rep",col="red",alpha=0.5,legend.show=FALSE)+
tm_layout(title = "Texas", frame = FALSE, bg.color = NA)
black=tm_shape(tx.data) +tm_fill(col = "dist",palette = "viridis",legend.show=FALSE,alpha=0.4)+
tm_dots(size = "eth1_aa",col="black",alpha=0.5,legend.show=FALSE)+
tm_layout(title = "Texas", frame = FALSE, bg.color = NA)
white=tm_shape(tx.data) +tm_fill(col = "dist",palette = "viridis",legend.show=FALSE,alpha=0.4)+
tm_dots(size = "eth1_eur",col="yellow",alpha=0.5,legend.show=FALSE)+
tm_layout(title = "Texas", frame = FALSE, bg.color = NA)
hisp=tm_shape(tx.data) +tm_fill(col = "dist",palette = "viridis",legend.show=FALSE,alpha=0.4)+tm_dots(size = "eth1_hisp",col="brown",alpha=0.5,legend.show=FALSE)+tm_layout(title = "Texas", frame = FALSE, bg.color = NA)
asian=tm_shape(tx.data) +tm_fill(col = "dist",palette = "viridis",legend.show=FALSE,alpha=0.4)+tm_dots(size = "eth1_esa",col="orange",alpha=0.5,legend.show=FALSE)+tm_layout(title = "Texas", frame = FALSE, bg.color = NA)
tmap_arrange(black,white,hisp,asian,dem,rep,nrow = 2,ncol=4)
Legend labels were too wide. Therefore, legend.text.size has been set to 0.59. Increase legend.width (argument of tm_layout) to make the legend wider and therefore the labels larger.
Legend labels were too wide. Therefore, legend.text.size has been set to 0.59. Increase legend.width (argument of tm_layout) to make the legend wider and therefore the labels larger.

NA
library(ggplot2)
library(dplyr)
library(ggsci)
library(qte)
Registered S3 method overwritten by 'data.table':
method from
print.data.table
library(CVXR)
Attaching package: ‘CVXR’
The following object is masked from ‘package:dplyr’:
id
The following object is masked from ‘package:stats’:
power
load("data/power.data.RData")
###### My own Quantile treatment effect model
quantile=function(taus, y, wt){
# minimize sum of check functions
q <- Variable(1)
quant_loss <- function(u, tau) { 0.5 * abs(u) + (tau - 0.5) * u }
solutions <- sapply(taus, function(tau) {
obj <- sum(wt*quant_loss(y-q,tau))
prob <- Problem(Minimize(obj))
## THE OSQP solver returns an error for tau = 0.5
solve(prob, solver = "ECOS")$getValue(q)
})
return(solutions)
}
QTE=function(dataset, taus){
#pscore.reg <- glm(T ~ , data=dataset, family=binomial)
#pscore <- fitted(pscore.reg)
q.trt=quantile(taus=taus, y=dataset$Y, wt=dataset$T*dataset$eth1_hisp)
q.control=quantile(taus=taus, y=dataset$Y, wt=(1-dataset$T)*dataset$eth1_hisp)
return(q.trt-q.control)
}
#unique(power.data$STATE)
power.data%>%
mutate(black.power=black.power*100,
white.power=white.power*100,
hisp.power=hisp.power*100,
asian.power=asian.power*100)%>%
mutate(A=ifelse(STATE %in% c("Arizona","California","Hawaii","Idaho","Montana","New Jersey","Washington","Alaska","Arkansas","Colorado","Missouri","Ohio","Pennsylvania","Iowa"),
"Nonpartisan or bipartisan commissions",
ifelse(STATE %in% c("Delaware","Illinois","Maryland","Massachusetts","Nevada","New Mexico","New York","Oregon","Rhode Island"),
"Democratic",
ifelse(STATE %in% c("Alabama","Florida","Georgia","Indiana","Kansas","Kentucky","Mississippi","New Hampshire","North Carolina","North Dakota","Oklahoma","South Carolina","South Dakota","Tennessee","Texas","Utah","West Virginia","Wyoming"),"Republican",""))))%>%filter(A !="")%>%
ggplot()+
geom_density(aes(x=white.power,y=..scaled..,weight=eth1_eur,group=A,col=A))+
scale_color_startrek()+
ggtitle("White voter power")

power.data%>%
mutate(black.power=black.power*100,
white.power=white.power*100,
hisp.power=hisp.power*100,
asian.power=asian.power*100)%>%
mutate(A=ifelse(STATE %in% c("Arizona","California","Hawaii","Idaho","Montana","New Jersey","Washington","Alaska","Arkansas","Colorado","Missouri","Ohio","Pennsylvania","Iowa"),
"Nonpartisan or bipartisan commissions",
ifelse(STATE %in% c("Delaware","Illinois","Maryland","Massachusetts","Nevada","New Mexico","New York","Oregon","Rhode Island"),
"Democratic",
ifelse(STATE %in% c("Alabama","Florida","Georgia","Indiana","Kansas","Kentucky","Mississippi","New Hampshire","North Carolina","North Dakota","Oklahoma","South Carolina","South Dakota","Tennessee","Texas","Utah","West Virginia","Wyoming"),"Republican",""))))%>%filter(A !="")%>%
ggplot()+
geom_density(alpha=0.1,aes(x=black.power,y=..scaled..,weight=eth1_aa,group=A,col=A))+scale_color_startrek()+
ggtitle("Black voter power")

power.data%>%
mutate(black.power=black.power*100,
white.power=white.power*100,
hisp.power=hisp.power*100,
asian.power=asian.power*100)%>%
mutate(A=ifelse(STATE %in% c("Arizona","California","Hawaii","Idaho","Montana","New Jersey","Washington","Alaska","Arkansas","Colorado","Missouri","Ohio","Pennsylvania","Iowa"),
"Nonpartisan or bipartisan commissions",
ifelse(STATE %in% c("Delaware","Illinois","Maryland","Massachusetts","Nevada","New Mexico","New York","Oregon","Rhode Island"),
"Democratic",
ifelse(STATE %in% c("Alabama","Florida","Georgia","Indiana","Kansas","Kentucky","Mississippi","New Hampshire","North Carolina","North Dakota","Oklahoma","South Carolina","South Dakota","Tennessee","Texas","Utah","West Virginia","Wyoming"),"Republican",""))))%>%filter(A !="")%>%
ggplot()+
geom_density(alpha=0.1,aes(x=hisp.power,y=..scaled..,weight=eth1_hisp,group=A,col=A))+scale_color_startrek()+
ggtitle("Hisp voter power")

power.data%>%
mutate(black.power=black.power*100,
white.power=white.power*100,
hisp.power=hisp.power*100,
asian.power=asian.power*100)%>%
mutate(A=ifelse(STATE %in% c("Arizona","California","Hawaii","Idaho","Montana","New Jersey","Washington","Alaska","Arkansas","Colorado","Missouri","Ohio","Pennsylvania","Iowa"),
"Nonpartisan or bipartisan commissions",
ifelse(STATE %in% c("Delaware","Illinois","Maryland","Massachusetts","Nevada","New Mexico","New York","Oregon","Rhode Island"),
"Democratic",
ifelse(STATE %in% c("Alabama","Florida","Georgia","Indiana","Kansas","Kentucky","Mississippi","New Hampshire","North Carolina","North Dakota","Oklahoma","South Carolina","South Dakota","Tennessee","Texas","Utah","West Virginia","Wyoming"),"Republican",""))))%>%filter(A !="")%>%
ggplot()+
geom_density(alpha=0.1,aes(x=asian.power,y=..scaled..,weight=eth1_esa,group=A,col=A))+scale_color_startrek()+
ggtitle("Asian voter power")

#table(power.data$STATE,power.data$A)
#unique(power.data$STATE)
power.data=power.data%>%
mutate(black.power=black.power*100,
white.power=white.power*100,
hisp.power=hisp.power*100,
asian.power=asian.power*100)%>%
mutate(A=ifelse(STATE %in% c("Arizona","California","Hawaii","Idaho","Montana","New Jersey","Washington","Alaska","Arkansas","Colorado","Missouri","Ohio","Pennsylvania","Iowa"),
"Nonpartisan or bipartisan commissions",
ifelse(STATE %in% c("Delaware","Illinois","Maryland","Massachusetts","Nevada","New Mexico","New York","Oregon","Rhode Island"),
"Democratic",
ifelse(STATE %in% c("Alabama","Florida","Georgia","Indiana","Kansas","Kentucky","Mississippi","New Hampshire","North Carolina","North Dakota","Oklahoma","South Carolina","South Dakota","Tennessee","Texas","Utah","West Virginia","Wyoming"),"Republican",""))))%>%
filter(A %in% c("Republican","Nonpartisan or bipartisan commissions"))%>%mutate(T=ifelse(A=="Republican",1,0))
#table(power.data$STATE,power.data$A)
taus=c(0.05,0.1, 0.25, 0.5, 0.75, 0.90, 0.95)
q.trt=quantile(taus=taus, y=power.data$black.power, wt=power.data$T*power.data$eth1_aa)
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
q.control=quantile(taus=taus, y=power.data$black.power, wt=(1-power.data$T)*power.data$eth1_aa)
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
black.qte=q.trt-q.control
#plot(c(0.05,0.1, 0.25, 0.5, 0.75, 0.90, 0.95),black.qte,type="b")
q.trt=quantile(taus=taus, y=power.data$white.power, wt=power.data$T*power.data$eth1_eur)
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
q.control=quantile(taus=taus, y=power.data$white.power, wt=(1-power.data$T)*power.data$eth1_eur)
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
white.qte=q.trt-q.control
#plot(c(0.05,0.1, 0.25, 0.5, 0.75, 0.90, 0.95),white.qte,type="b")
q.trt=quantile(taus=taus, y=power.data$hisp.power, wt=power.data$T*power.data$eth1_hisp)
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
q.control=quantile(taus=taus, y=power.data$hisp.power, wt=(1-power.data$T)*power.data$eth1_hisp)
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
hisp.qte=q.trt-q.control
#plot(c(0.05,0.1, 0.25, 0.5, 0.75, 0.90, 0.95),hisp.qte,type="b")
q.trt=quantile(taus=taus, y=power.data$asian.power, wt=power.data$T*power.data$eth1_esa)
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
q.control=quantile(taus=taus, y=power.data$asian.power, wt=(1-power.data$T)*power.data$eth1_esa)
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
Warning in size(const) : NAs introduced by coercion to integer range
asian.qte=q.trt-q.control
#plot(c(0.05,0.1, 0.25, 0.5, 0.75, 0.90, 0.95),asian.qte,type="b")
data.frame(q=rep(c(0.05,0.1, 0.25, 0.5, 0.75, 0.90, 0.95),4),qte=c(black.qte,white.qte,hisp.qte,asian.qte),race=rep(c("Black","White","Hispanic","Asian"),each=7))%>%
ggplot(aes(x=q,y=qte,col=race))+
geom_point()+
geom_line()+
scale_color_startrek()

LS0tCnRpdGxlOiAiR2VycnltYW5kZXJpbmcgTm90ZWJvb2siCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCmBgYHtyfQpsaWJyYXJ5KHNmKSAgICAgICAgICAjIGNsYXNzZXMgYW5kIGZ1bmN0aW9ucyBmb3IgdmVjdG9yIGRhdGEKbGlicmFyeShzcERhdGEpICAgICAgICAjIGxvYWQgZ2VvZ3JhcGhpYyBkYXRhCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodG1hcCkgICAgIyBmb3Igc3RhdGljIGFuZCBpbnRlcmFjdGl2ZSBtYXBzCmxpYnJhcnkoZ2dwbG90MikgCmxpYnJhcnkoZ2dzY2kpCmxpYnJhcnkodG9vbHMpCmxpYnJhcnkocmVhZHIpCgpsaWJyYXJ5KGZvcmVhY2gpCmxpYnJhcnkoZG9QYXJhbGxlbCkKCnJlZ2lzdGVyRG9QYXJhbGxlbChkZXRlY3RDb3JlcygpKQpnZXREb1BhcldvcmtlcnMoKQpgYGAKCgpgYGB7cixmaWcud2lkdGg9MTAsZmlnLmhlaWdodD01fQp2aXM9ZnVuY3Rpb24oc3RhdGUpewogICNzdGF0ZT0nYWwnCiAgbG9hZChwYXN0ZSgiZGF0YS8iLHN0YXRlLCIuZGF0YS5SRGF0YSIsc2VwPScnKSkKICBkYXRzZXQ9cGFzdGUoc3RhdGUsIi5kYXRhIixzZXA9JycpCiAgZGVtPXRtX3NoYXBlKG5vcXVvdGUoZGF0c2V0KSkgK3RtX2ZpbGwoY29sID0gImRpc3QiLHBhbGV0dGUgPSAidmlyaWRpcyIsbGVnZW5kLnNob3c9RkFMU0UsYWxwaGE9MC40KSt0bV9kb3RzKHNpemUgPSAicGFydHlfZGVtIixjb2w9ImJsdWUiLGFscGhhPTAuNSxsZWdlbmQuc2hvdz1GQUxTRSkrdG1fbGF5b3V0KHRpdGxlID0gc3RhdGUsIGZyYW1lID0gRkFMU0UsIGJnLmNvbG9yID0gTkEpCiAgcmVwPXRtX3NoYXBlKG5vcXVvdGUoZGF0c2V0KSkgK3RtX2ZpbGwoY29sID0gImRpc3QiLHBhbGV0dGUgPSAidmlyaWRpcyIsbGVnZW5kLnNob3c9RkFMU0UsYWxwaGE9MC40KSt0bV9kb3RzKHNpemUgPSAicGFydHlfcmVwIixjb2w9InJlZCIsYWxwaGE9MC41LGxlZ2VuZC5zaG93PUZBTFNFKSt0bV9sYXlvdXQodGl0bGUgPSAnJywgZnJhbWUgPSBGQUxTRSwgYmcuY29sb3IgPSBOQSkKICBibGFjaz10bV9zaGFwZShub3F1b3RlKGRhdHNldCkpICt0bV9maWxsKGNvbCA9ICJkaXN0IixwYWxldHRlID0gInZpcmlkaXMiLGxlZ2VuZC5zaG93PUZBTFNFLGFscGhhPTAuNCkrdG1fZG90cyhzaXplID0gImV0aDFfYWEiLGNvbD0iYmxhY2siLGFscGhhPTAuNSxsZWdlbmQuc2hvdz1GQUxTRSkrIHRtX2xheW91dCh0aXRsZSA9ICIiLCBmcmFtZSA9IEZBTFNFLCBiZy5jb2xvciA9IE5BKQogIHdoaXRlPXRtX3NoYXBlKG5vcXVvdGUoZGF0c2V0KSkgK3RtX2ZpbGwoY29sID0gImRpc3QiLHBhbGV0dGUgPSAidmlyaWRpcyIsbGVnZW5kLnNob3c9RkFMU0UsYWxwaGE9MC40KSt0bV9kb3RzKHNpemUgPSAiZXRoMV9ldXIiLGNvbD0ieWVsbG93IixhbHBoYT0wLjUsbGVnZW5kLnNob3c9RkFMU0UpK3RtX2xheW91dCh0aXRsZSA9ICIiLCBmcmFtZSA9IEZBTFNFLCBiZy5jb2xvciA9IE5BKQogIGhpc3A9dG1fc2hhcGUobm9xdW90ZShkYXRzZXQpKSArdG1fZmlsbChjb2wgPSAiZGlzdCIscGFsZXR0ZSA9ICJ2aXJpZGlzIixsZWdlbmQuc2hvdz1GQUxTRSxhbHBoYT0wLjQpK3RtX2RvdHMoc2l6ZSA9ICJldGgxX2hpc3AiLGNvbD0iYnJvd24iLGFscGhhPTAuNSxsZWdlbmQuc2hvdz1GQUxTRSkrdG1fbGF5b3V0KHRpdGxlID0gIiIsIGZyYW1lID0gRkFMU0UsIGJnLmNvbG9yID0gTkEpCiAgYXNpYW49dG1fc2hhcGUobm9xdW90ZShkYXRzZXQpKSArdG1fZmlsbChjb2wgPSAiZGlzdCIscGFsZXR0ZSA9ICJ2aXJpZGlzIixsZWdlbmQuc2hvdz1GQUxTRSxhbHBoYT0wLjQpK3RtX2RvdHMoc2l6ZSA9ICJldGgxX2VzYSIsY29sPSJvcmFuZ2UiLGFscGhhPTAuNSxsZWdlbmQuc2hvdz1GQUxTRSkrdG1fbGF5b3V0KHRpdGxlID0gIiIsIGZyYW1lID0gRkFMU0UsIGJnLmNvbG9yID0gTkEpCiAgcD10bWFwX2FycmFuZ2UoYmxhY2ssd2hpdGUsaGlzcCxhc2lhbixkZW0scmVwLAogICAgICAgICAgICAgbnJvdyA9IDIsbmNvbD00KQpyZXR1cm4ocCkKCiAgCn0Kc3RhdGUxPXN1YnN0cihsaXN0LmZpbGVzKCIvaG9tZS96aG91eDEwNC9SL0dlcnJ5L2NvbmdyZXNzaW9uYWwyMDEwIiksMSwyKQpzdGF0ZTI9c3Vic3RyKGxpc3QuZmlsZXMoIi9ob21lL3pob3V4MTA0L1IvR2VycnkvYmxvY2syMDEwIiksMSwyKQpzdGF0ZTM9dG9sb3dlcihzdWJzdHIobGlzdC5maWxlcygiL2hvbWUvemhvdXgxMDQvUi9HZXJyeS92b3RlcjIwMjEiKSwxLDIpKQpzdGF0ZXM9aW50ZXJzZWN0KGludGVyc2VjdChzdGF0ZTEsc3RhdGUyKSxzdGF0ZTMpCgpmb3IocyBpbiAxOmxlbmd0aChzdGF0ZXMpKXsKICBzPTEKICBpZihzdGF0ZXNbc10hPSdjbycgJiBzdGF0ZXNbc10hPSdmbCcpewogICAgcD12aXMoc3RhdGVzW3NdKQogICAgcHJpbnQocCkKICB9CiAgCn0KCgpsb2FkKCJkYXRhL2NhLmRhdGEuUkRhdGEiKQpkZW09dG1fc2hhcGUoY2EuZGF0YSkgK3RtX2ZpbGwoY29sID0gImRpc3QiLHBhbGV0dGUgPSAidmlyaWRpcyIsbGVnZW5kLnNob3c9RkFMU0UsYWxwaGE9MC40KSsKICB0bV9kb3RzKHNpemUgPSAicGFydHlfZGVtIixjb2w9ImJsdWUiLGFscGhhPTAuNSxsZWdlbmQuc2hvdz1GQUxTRSkrCiAgdG1fbGF5b3V0KHRpdGxlID0gIkNhbGlmb3JuaWEiLCBmcmFtZSA9IEZBTFNFLCBiZy5jb2xvciA9IE5BKQpyZXA9dG1fc2hhcGUoY2EuZGF0YSkgK3RtX2ZpbGwoY29sID0gImRpc3QiLHBhbGV0dGUgPSAidmlyaWRpcyIsbGVnZW5kLnNob3c9RkFMU0UsYWxwaGE9MC40KSsKICB0bV9kb3RzKHNpemUgPSAicGFydHlfcmVwIixjb2w9InJlZCIsYWxwaGE9MC41LGxlZ2VuZC5zaG93PUZBTFNFKSsKICB0bV9sYXlvdXQodGl0bGUgPSAiQ2FsaWZvcm5pYSIsIGZyYW1lID0gRkFMU0UsIGJnLmNvbG9yID0gTkEpCmJsYWNrPXRtX3NoYXBlKGNhLmRhdGEpICt0bV9maWxsKGNvbCA9ICJkaXN0IixwYWxldHRlID0gInZpcmlkaXMiLGxlZ2VuZC5zaG93PUZBTFNFLGFscGhhPTAuNCkrCiAgdG1fZG90cyhzaXplID0gImV0aDFfYWEiLGNvbD0iYmxhY2siLGFscGhhPTAuNSxsZWdlbmQuc2hvdz1GQUxTRSkrCiAgdG1fbGF5b3V0KHRpdGxlID0gIkNhbGlmb3JuaWEiLCBmcmFtZSA9IEZBTFNFLCBiZy5jb2xvciA9IE5BKQp3aGl0ZT10bV9zaGFwZShjYS5kYXRhKSArdG1fZmlsbChjb2wgPSAiZGlzdCIscGFsZXR0ZSA9ICJ2aXJpZGlzIixsZWdlbmQuc2hvdz1GQUxTRSxhbHBoYT0wLjQpKwogIHRtX2RvdHMoc2l6ZSA9ICJldGgxX2V1ciIsY29sPSJ5ZWxsb3ciLGFscGhhPTAuNSxsZWdlbmQuc2hvdz1GQUxTRSkrCiAgdG1fbGF5b3V0KHRpdGxlID0gIkNhbGlmb3JuaWEiLCBmcmFtZSA9IEZBTFNFLCBiZy5jb2xvciA9IE5BKQpoaXNwPXRtX3NoYXBlKGNhLmRhdGEpICt0bV9maWxsKGNvbCA9ICJkaXN0IixwYWxldHRlID0gInZpcmlkaXMiLGxlZ2VuZC5zaG93PUZBTFNFLGFscGhhPTAuNCkrdG1fZG90cyhzaXplID0gImV0aDFfaGlzcCIsY29sPSJicm93biIsYWxwaGE9MC41LGxlZ2VuZC5zaG93PUZBTFNFKSt0bV9sYXlvdXQodGl0bGUgPSAiQ2FsaWZvcm5pYSIsIGZyYW1lID0gRkFMU0UsIGJnLmNvbG9yID0gTkEpCmFzaWFuPXRtX3NoYXBlKGNhLmRhdGEpICt0bV9maWxsKGNvbCA9ICJkaXN0IixwYWxldHRlID0gInZpcmlkaXMiLGxlZ2VuZC5zaG93PUZBTFNFLGFscGhhPTAuNCkrdG1fZG90cyhzaXplID0gImV0aDFfZXNhIixjb2w9Im9yYW5nZSIsYWxwaGE9MC41LGxlZ2VuZC5zaG93PUZBTFNFKSt0bV9sYXlvdXQodGl0bGUgPSAiQ2FsaWZvcm5pYSIsIGZyYW1lID0gRkFMU0UsIGJnLmNvbG9yID0gTkEpCgoKdG1hcF9hcnJhbmdlKGJsYWNrLHdoaXRlLGhpc3AsYXNpYW4sZGVtLHJlcCxucm93ID0gMixuY29sPTQpCgogCmBgYAoKYGBge3IsZmlnLndpZHRoPTEwLGZpZy5oZWlnaHQ9NX0KbG9hZCgiZGF0YS90eC5kYXRhLlJEYXRhIikKZGVtPXRtX3NoYXBlKHR4LmRhdGEpICt0bV9maWxsKGNvbCA9ICJkaXN0IixwYWxldHRlID0gInZpcmlkaXMiLGxlZ2VuZC5zaG93PUZBTFNFLGFscGhhPTAuNCkrCiAgdG1fZG90cyhzaXplID0gInBhcnR5X2RlbSIsY29sPSJibHVlIixhbHBoYT0wLjUsbGVnZW5kLnNob3c9RkFMU0UpKwogIHRtX2xheW91dCh0aXRsZSA9ICJUZXhhcyIsIGZyYW1lID0gRkFMU0UsIGJnLmNvbG9yID0gTkEpCnJlcD10bV9zaGFwZSh0eC5kYXRhKSArdG1fZmlsbChjb2wgPSAiZGlzdCIscGFsZXR0ZSA9ICJ2aXJpZGlzIixsZWdlbmQuc2hvdz1GQUxTRSxhbHBoYT0wLjQpKwogIHRtX2RvdHMoc2l6ZSA9ICJwYXJ0eV9yZXAiLGNvbD0icmVkIixhbHBoYT0wLjUsbGVnZW5kLnNob3c9RkFMU0UpKwogIHRtX2xheW91dCh0aXRsZSA9ICJUZXhhcyIsIGZyYW1lID0gRkFMU0UsIGJnLmNvbG9yID0gTkEpCmJsYWNrPXRtX3NoYXBlKHR4LmRhdGEpICt0bV9maWxsKGNvbCA9ICJkaXN0IixwYWxldHRlID0gInZpcmlkaXMiLGxlZ2VuZC5zaG93PUZBTFNFLGFscGhhPTAuNCkrCiAgdG1fZG90cyhzaXplID0gImV0aDFfYWEiLGNvbD0iYmxhY2siLGFscGhhPTAuNSxsZWdlbmQuc2hvdz1GQUxTRSkrCiAgdG1fbGF5b3V0KHRpdGxlID0gIlRleGFzIiwgZnJhbWUgPSBGQUxTRSwgYmcuY29sb3IgPSBOQSkKd2hpdGU9dG1fc2hhcGUodHguZGF0YSkgK3RtX2ZpbGwoY29sID0gImRpc3QiLHBhbGV0dGUgPSAidmlyaWRpcyIsbGVnZW5kLnNob3c9RkFMU0UsYWxwaGE9MC40KSsKICB0bV9kb3RzKHNpemUgPSAiZXRoMV9ldXIiLGNvbD0ieWVsbG93IixhbHBoYT0wLjUsbGVnZW5kLnNob3c9RkFMU0UpKwogIHRtX2xheW91dCh0aXRsZSA9ICJUZXhhcyIsIGZyYW1lID0gRkFMU0UsIGJnLmNvbG9yID0gTkEpCmhpc3A9dG1fc2hhcGUodHguZGF0YSkgK3RtX2ZpbGwoY29sID0gImRpc3QiLHBhbGV0dGUgPSAidmlyaWRpcyIsbGVnZW5kLnNob3c9RkFMU0UsYWxwaGE9MC40KSt0bV9kb3RzKHNpemUgPSAiZXRoMV9oaXNwIixjb2w9ImJyb3duIixhbHBoYT0wLjUsbGVnZW5kLnNob3c9RkFMU0UpK3RtX2xheW91dCh0aXRsZSA9ICJUZXhhcyIsIGZyYW1lID0gRkFMU0UsIGJnLmNvbG9yID0gTkEpCmFzaWFuPXRtX3NoYXBlKHR4LmRhdGEpICt0bV9maWxsKGNvbCA9ICJkaXN0IixwYWxldHRlID0gInZpcmlkaXMiLGxlZ2VuZC5zaG93PUZBTFNFLGFscGhhPTAuNCkrdG1fZG90cyhzaXplID0gImV0aDFfZXNhIixjb2w9Im9yYW5nZSIsYWxwaGE9MC41LGxlZ2VuZC5zaG93PUZBTFNFKSt0bV9sYXlvdXQodGl0bGUgPSAiVGV4YXMiLCBmcmFtZSA9IEZBTFNFLCBiZy5jb2xvciA9IE5BKQoKCnRtYXBfYXJyYW5nZShibGFjayx3aGl0ZSxoaXNwLGFzaWFuLGRlbSxyZXAsbnJvdyA9IDIsbmNvbD00KQogCmBgYAoKCgoKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShkcGx5cikKbGlicmFyeShnZ3NjaSkKbGlicmFyeShxdGUpCmxpYnJhcnkoQ1ZYUikKYGBgCgoKYGBge3IsZmlnLndpZHRoPTgsZmlnLmhlaWdodD01fQoKbG9hZCgiZGF0YS9wb3dlci5kYXRhLlJEYXRhIikKCiMjIyMjIyBNeSBvd24gUXVhbnRpbGUgdHJlYXRtZW50IGVmZmVjdCBtb2RlbAoKCnF1YW50aWxlPWZ1bmN0aW9uKHRhdXMsIHksIHd0KXsKIAogICMgbWluaW1pemUgc3VtIG9mIGNoZWNrIGZ1bmN0aW9ucwogIAogIHEgPC0gVmFyaWFibGUoMSkKICBxdWFudF9sb3NzIDwtIGZ1bmN0aW9uKHUsIHRhdSkgeyAwLjUgKiBhYnModSkgKyAodGF1IC0gMC41KSAqIHUgfQogIHNvbHV0aW9ucyA8LSBzYXBwbHkodGF1cywgZnVuY3Rpb24odGF1KSB7CiAgICBvYmogPC0gc3VtKHd0KnF1YW50X2xvc3MoeS1xLHRhdSkpCiAgICBwcm9iIDwtIFByb2JsZW0oTWluaW1pemUob2JqKSkKICAgICMjIFRIRSBPU1FQIHNvbHZlciByZXR1cm5zIGFuIGVycm9yIGZvciB0YXUgPSAwLjUKICAgIHNvbHZlKHByb2IsIHNvbHZlciA9ICJFQ09TIikkZ2V0VmFsdWUocSkKICB9KQogIHJldHVybihzb2x1dGlvbnMpCn0KClFURT1mdW5jdGlvbihkYXRhc2V0LCB0YXVzKXsKICAKICAKICAjcHNjb3JlLnJlZyA8LSBnbG0oVCB+ICwgZGF0YT1kYXRhc2V0LCBmYW1pbHk9Ymlub21pYWwpCiAgI3BzY29yZSA8LSBmaXR0ZWQocHNjb3JlLnJlZykKICAKICBxLnRydD1xdWFudGlsZSh0YXVzPXRhdXMsIHk9ZGF0YXNldCRZLCB3dD1kYXRhc2V0JFQqZGF0YXNldCRldGgxX2hpc3ApCiAgcS5jb250cm9sPXF1YW50aWxlKHRhdXM9dGF1cywgeT1kYXRhc2V0JFksIHd0PSgxLWRhdGFzZXQkVCkqZGF0YXNldCRldGgxX2hpc3ApCiAgcmV0dXJuKHEudHJ0LXEuY29udHJvbCkKICAKfQoKI3VuaXF1ZShwb3dlci5kYXRhJFNUQVRFKQpwb3dlci5kYXRhJT4lCiAgbXV0YXRlKGJsYWNrLnBvd2VyPWJsYWNrLnBvd2VyKjEwMCwKICAgICAgICAgd2hpdGUucG93ZXI9d2hpdGUucG93ZXIqMTAwLAogICAgICAgICBoaXNwLnBvd2VyPWhpc3AucG93ZXIqMTAwLAogICAgICAgICBhc2lhbi5wb3dlcj1hc2lhbi5wb3dlcioxMDApJT4lCiAgbXV0YXRlKEE9aWZlbHNlKFNUQVRFICVpbiUgYygiQXJpem9uYSIsIkNhbGlmb3JuaWEiLCJIYXdhaWkiLCJJZGFobyIsIk1vbnRhbmEiLCJOZXcgSmVyc2V5IiwiV2FzaGluZ3RvbiIsIkFsYXNrYSIsIkFya2Fuc2FzIiwiQ29sb3JhZG8iLCJNaXNzb3VyaSIsIk9oaW8iLCJQZW5uc3lsdmFuaWEiLCJJb3dhIiksCiAgICAgICAgICAgICAgICAgICJOb25wYXJ0aXNhbiBvciBiaXBhcnRpc2FuIGNvbW1pc3Npb25zIiwKICAgICAgICAgICAgICAgICAgaWZlbHNlKFNUQVRFICVpbiUgYygiRGVsYXdhcmUiLCJJbGxpbm9pcyIsIk1hcnlsYW5kIiwiTWFzc2FjaHVzZXR0cyIsIk5ldmFkYSIsIk5ldyBNZXhpY28iLCJOZXcgWW9yayIsIk9yZWdvbiIsIlJob2RlIElzbGFuZCIpLAogICAgICAgICAgICAgICAgICAgICAgICAgIkRlbW9jcmF0aWMiLAogICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKFNUQVRFICVpbiUgYygiQWxhYmFtYSIsIkZsb3JpZGEiLCJHZW9yZ2lhIiwiSW5kaWFuYSIsIkthbnNhcyIsIktlbnR1Y2t5IiwiTWlzc2lzc2lwcGkiLCJOZXcgSGFtcHNoaXJlIiwiTm9ydGggQ2Fyb2xpbmEiLCJOb3J0aCBEYWtvdGEiLCJPa2xhaG9tYSIsIlNvdXRoIENhcm9saW5hIiwiU291dGggRGFrb3RhIiwiVGVubmVzc2VlIiwiVGV4YXMiLCJVdGFoIiwiV2VzdCBWaXJnaW5pYSIsIld5b21pbmciKSwiUmVwdWJsaWNhbiIsIiIpKSkpJT4lZmlsdGVyKEEgIT0iIiklPiUKICBnZ3Bsb3QoKSsKICBnZW9tX2RlbnNpdHkoYWVzKHg9d2hpdGUucG93ZXIseT0uLnNjYWxlZC4uLHdlaWdodD1ldGgxX2V1cixncm91cD1BLGNvbD1BKSkrCiAgc2NhbGVfY29sb3Jfc3RhcnRyZWsoKSsKICBnZ3RpdGxlKCJXaGl0ZSB2b3RlciBwb3dlciIpCgpwb3dlci5kYXRhJT4lCiAgbXV0YXRlKGJsYWNrLnBvd2VyPWJsYWNrLnBvd2VyKjEwMCwKICAgICAgICAgd2hpdGUucG93ZXI9d2hpdGUucG93ZXIqMTAwLAogICAgICAgICBoaXNwLnBvd2VyPWhpc3AucG93ZXIqMTAwLAogICAgICAgICBhc2lhbi5wb3dlcj1hc2lhbi5wb3dlcioxMDApJT4lCiAgbXV0YXRlKEE9aWZlbHNlKFNUQVRFICVpbiUgYygiQXJpem9uYSIsIkNhbGlmb3JuaWEiLCJIYXdhaWkiLCJJZGFobyIsIk1vbnRhbmEiLCJOZXcgSmVyc2V5IiwiV2FzaGluZ3RvbiIsIkFsYXNrYSIsIkFya2Fuc2FzIiwiQ29sb3JhZG8iLCJNaXNzb3VyaSIsIk9oaW8iLCJQZW5uc3lsdmFuaWEiLCJJb3dhIiksCiAgICAgICAgICAgICAgICAgICJOb25wYXJ0aXNhbiBvciBiaXBhcnRpc2FuIGNvbW1pc3Npb25zIiwKICAgICAgICAgICAgICAgICAgaWZlbHNlKFNUQVRFICVpbiUgYygiRGVsYXdhcmUiLCJJbGxpbm9pcyIsIk1hcnlsYW5kIiwiTWFzc2FjaHVzZXR0cyIsIk5ldmFkYSIsIk5ldyBNZXhpY28iLCJOZXcgWW9yayIsIk9yZWdvbiIsIlJob2RlIElzbGFuZCIpLAogICAgICAgICAgICAgICAgICAgICAgICAgIkRlbW9jcmF0aWMiLAogICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKFNUQVRFICVpbiUgYygiQWxhYmFtYSIsIkZsb3JpZGEiLCJHZW9yZ2lhIiwiSW5kaWFuYSIsIkthbnNhcyIsIktlbnR1Y2t5IiwiTWlzc2lzc2lwcGkiLCJOZXcgSGFtcHNoaXJlIiwiTm9ydGggQ2Fyb2xpbmEiLCJOb3J0aCBEYWtvdGEiLCJPa2xhaG9tYSIsIlNvdXRoIENhcm9saW5hIiwiU291dGggRGFrb3RhIiwiVGVubmVzc2VlIiwiVGV4YXMiLCJVdGFoIiwiV2VzdCBWaXJnaW5pYSIsIld5b21pbmciKSwiUmVwdWJsaWNhbiIsIiIpKSkpJT4lZmlsdGVyKEEgIT0iIiklPiUKICBnZ3Bsb3QoKSsKICBnZW9tX2RlbnNpdHkoYWxwaGE9MC4xLGFlcyh4PWJsYWNrLnBvd2VyLHk9Li5zY2FsZWQuLix3ZWlnaHQ9ZXRoMV9hYSxncm91cD1BLGNvbD1BKSkrc2NhbGVfY29sb3Jfc3RhcnRyZWsoKSsKICBnZ3RpdGxlKCJCbGFjayB2b3RlciBwb3dlciIpCiAKcG93ZXIuZGF0YSU+JQogIG11dGF0ZShibGFjay5wb3dlcj1ibGFjay5wb3dlcioxMDAsCiAgICAgICAgIHdoaXRlLnBvd2VyPXdoaXRlLnBvd2VyKjEwMCwKICAgICAgICAgaGlzcC5wb3dlcj1oaXNwLnBvd2VyKjEwMCwKICAgICAgICAgYXNpYW4ucG93ZXI9YXNpYW4ucG93ZXIqMTAwKSU+JQogIG11dGF0ZShBPWlmZWxzZShTVEFURSAlaW4lIGMoIkFyaXpvbmEiLCJDYWxpZm9ybmlhIiwiSGF3YWlpIiwiSWRhaG8iLCJNb250YW5hIiwiTmV3IEplcnNleSIsIldhc2hpbmd0b24iLCJBbGFza2EiLCJBcmthbnNhcyIsIkNvbG9yYWRvIiwiTWlzc291cmkiLCJPaGlvIiwiUGVubnN5bHZhbmlhIiwiSW93YSIpLAogICAgICAgICAgICAgICAgICAiTm9ucGFydGlzYW4gb3IgYmlwYXJ0aXNhbiBjb21taXNzaW9ucyIsCiAgICAgICAgICAgICAgICAgIGlmZWxzZShTVEFURSAlaW4lIGMoIkRlbGF3YXJlIiwiSWxsaW5vaXMiLCJNYXJ5bGFuZCIsIk1hc3NhY2h1c2V0dHMiLCJOZXZhZGEiLCJOZXcgTWV4aWNvIiwiTmV3IFlvcmsiLCJPcmVnb24iLCJSaG9kZSBJc2xhbmQiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICJEZW1vY3JhdGljIiwKICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShTVEFURSAlaW4lIGMoIkFsYWJhbWEiLCJGbG9yaWRhIiwiR2VvcmdpYSIsIkluZGlhbmEiLCJLYW5zYXMiLCJLZW50dWNreSIsIk1pc3Npc3NpcHBpIiwiTmV3IEhhbXBzaGlyZSIsIk5vcnRoIENhcm9saW5hIiwiTm9ydGggRGFrb3RhIiwiT2tsYWhvbWEiLCJTb3V0aCBDYXJvbGluYSIsIlNvdXRoIERha290YSIsIlRlbm5lc3NlZSIsIlRleGFzIiwiVXRhaCIsIldlc3QgVmlyZ2luaWEiLCJXeW9taW5nIiksIlJlcHVibGljYW4iLCIiKSkpKSU+JWZpbHRlcihBICE9IiIpJT4lCiAgZ2dwbG90KCkrCiAgZ2VvbV9kZW5zaXR5KGFscGhhPTAuMSxhZXMoeD1oaXNwLnBvd2VyLHk9Li5zY2FsZWQuLix3ZWlnaHQ9ZXRoMV9oaXNwLGdyb3VwPUEsY29sPUEpKStzY2FsZV9jb2xvcl9zdGFydHJlaygpKwogIGdndGl0bGUoIkhpc3Agdm90ZXIgcG93ZXIiKQoKCnBvd2VyLmRhdGElPiUKICBtdXRhdGUoYmxhY2sucG93ZXI9YmxhY2sucG93ZXIqMTAwLAogICAgICAgICB3aGl0ZS5wb3dlcj13aGl0ZS5wb3dlcioxMDAsCiAgICAgICAgIGhpc3AucG93ZXI9aGlzcC5wb3dlcioxMDAsCiAgICAgICAgIGFzaWFuLnBvd2VyPWFzaWFuLnBvd2VyKjEwMCklPiUKICBtdXRhdGUoQT1pZmVsc2UoU1RBVEUgJWluJSBjKCJBcml6b25hIiwiQ2FsaWZvcm5pYSIsIkhhd2FpaSIsIklkYWhvIiwiTW9udGFuYSIsIk5ldyBKZXJzZXkiLCJXYXNoaW5ndG9uIiwiQWxhc2thIiwiQXJrYW5zYXMiLCJDb2xvcmFkbyIsIk1pc3NvdXJpIiwiT2hpbyIsIlBlbm5zeWx2YW5pYSIsIklvd2EiKSwKICAgICAgICAgICAgICAgICAgIk5vbnBhcnRpc2FuIG9yIGJpcGFydGlzYW4gY29tbWlzc2lvbnMiLAogICAgICAgICAgICAgICAgICBpZmVsc2UoU1RBVEUgJWluJSBjKCJEZWxhd2FyZSIsIklsbGlub2lzIiwiTWFyeWxhbmQiLCJNYXNzYWNodXNldHRzIiwiTmV2YWRhIiwiTmV3IE1leGljbyIsIk5ldyBZb3JrIiwiT3JlZ29uIiwiUmhvZGUgSXNsYW5kIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAiRGVtb2NyYXRpYyIsCiAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoU1RBVEUgJWluJSBjKCJBbGFiYW1hIiwiRmxvcmlkYSIsIkdlb3JnaWEiLCJJbmRpYW5hIiwiS2Fuc2FzIiwiS2VudHVja3kiLCJNaXNzaXNzaXBwaSIsIk5ldyBIYW1wc2hpcmUiLCJOb3J0aCBDYXJvbGluYSIsIk5vcnRoIERha290YSIsIk9rbGFob21hIiwiU291dGggQ2Fyb2xpbmEiLCJTb3V0aCBEYWtvdGEiLCJUZW5uZXNzZWUiLCJUZXhhcyIsIlV0YWgiLCJXZXN0IFZpcmdpbmlhIiwiV3lvbWluZyIpLCJSZXB1YmxpY2FuIiwiIikpKSklPiVmaWx0ZXIoQSAhPSIiKSU+JQogIGdncGxvdCgpKwogIGdlb21fZGVuc2l0eShhbHBoYT0wLjEsYWVzKHg9YXNpYW4ucG93ZXIseT0uLnNjYWxlZC4uLHdlaWdodD1ldGgxX2VzYSxncm91cD1BLGNvbD1BKSkrc2NhbGVfY29sb3Jfc3RhcnRyZWsoKSsKICBnZ3RpdGxlKCJBc2lhbiB2b3RlciBwb3dlciIpCiAKI3RhYmxlKHBvd2VyLmRhdGEkU1RBVEUscG93ZXIuZGF0YSRBKQpgYGAKCgpgYGB7cn0KI3VuaXF1ZShwb3dlci5kYXRhJFNUQVRFKQpwb3dlci5kYXRhPXBvd2VyLmRhdGElPiUKICBtdXRhdGUoYmxhY2sucG93ZXI9YmxhY2sucG93ZXIqMTAwLAogICAgICAgICB3aGl0ZS5wb3dlcj13aGl0ZS5wb3dlcioxMDAsCiAgICAgICAgIGhpc3AucG93ZXI9aGlzcC5wb3dlcioxMDAsCiAgICAgICAgIGFzaWFuLnBvd2VyPWFzaWFuLnBvd2VyKjEwMCklPiUKICBtdXRhdGUoQT1pZmVsc2UoU1RBVEUgJWluJSBjKCJBcml6b25hIiwiQ2FsaWZvcm5pYSIsIkhhd2FpaSIsIklkYWhvIiwiTW9udGFuYSIsIk5ldyBKZXJzZXkiLCJXYXNoaW5ndG9uIiwiQWxhc2thIiwiQXJrYW5zYXMiLCJDb2xvcmFkbyIsIk1pc3NvdXJpIiwiT2hpbyIsIlBlbm5zeWx2YW5pYSIsIklvd2EiKSwKICAgICAgICAgICAgICAgICAgIk5vbnBhcnRpc2FuIG9yIGJpcGFydGlzYW4gY29tbWlzc2lvbnMiLAogICAgICAgICAgICAgICAgICBpZmVsc2UoU1RBVEUgJWluJSBjKCJEZWxhd2FyZSIsIklsbGlub2lzIiwiTWFyeWxhbmQiLCJNYXNzYWNodXNldHRzIiwiTmV2YWRhIiwiTmV3IE1leGljbyIsIk5ldyBZb3JrIiwiT3JlZ29uIiwiUmhvZGUgSXNsYW5kIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAiRGVtb2NyYXRpYyIsCiAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoU1RBVEUgJWluJSBjKCJBbGFiYW1hIiwiRmxvcmlkYSIsIkdlb3JnaWEiLCJJbmRpYW5hIiwiS2Fuc2FzIiwiS2VudHVja3kiLCJNaXNzaXNzaXBwaSIsIk5ldyBIYW1wc2hpcmUiLCJOb3J0aCBDYXJvbGluYSIsIk5vcnRoIERha290YSIsIk9rbGFob21hIiwiU291dGggQ2Fyb2xpbmEiLCJTb3V0aCBEYWtvdGEiLCJUZW5uZXNzZWUiLCJUZXhhcyIsIlV0YWgiLCJXZXN0IFZpcmdpbmlhIiwiV3lvbWluZyIpLCJSZXB1YmxpY2FuIiwiIikpKSklPiUKICBmaWx0ZXIoQSAlaW4lIGMoIlJlcHVibGljYW4iLCJOb25wYXJ0aXNhbiBvciBiaXBhcnRpc2FuIGNvbW1pc3Npb25zIikpJT4lbXV0YXRlKFQ9aWZlbHNlKEE9PSJSZXB1YmxpY2FuIiwxLDApKQojdGFibGUocG93ZXIuZGF0YSRTVEFURSxwb3dlci5kYXRhJEEpCgp0YXVzPWMoMC4wNSwwLjEsIDAuMjUsIDAuNSwgMC43NSwgMC45MCwgMC45NSkKcS50cnQ9cXVhbnRpbGUodGF1cz10YXVzLCB5PXBvd2VyLmRhdGEkYmxhY2sucG93ZXIsIHd0PXBvd2VyLmRhdGEkVCpwb3dlci5kYXRhJGV0aDFfYWEpCnEuY29udHJvbD1xdWFudGlsZSh0YXVzPXRhdXMsIHk9cG93ZXIuZGF0YSRibGFjay5wb3dlciwgd3Q9KDEtcG93ZXIuZGF0YSRUKSpwb3dlci5kYXRhJGV0aDFfYWEpCmJsYWNrLnF0ZT1xLnRydC1xLmNvbnRyb2wKI3Bsb3QoYygwLjA1LDAuMSwgMC4yNSwgMC41LCAwLjc1LCAwLjkwLCAwLjk1KSxibGFjay5xdGUsdHlwZT0iYiIpCgpxLnRydD1xdWFudGlsZSh0YXVzPXRhdXMsIHk9cG93ZXIuZGF0YSR3aGl0ZS5wb3dlciwgd3Q9cG93ZXIuZGF0YSRUKnBvd2VyLmRhdGEkZXRoMV9ldXIpCnEuY29udHJvbD1xdWFudGlsZSh0YXVzPXRhdXMsIHk9cG93ZXIuZGF0YSR3aGl0ZS5wb3dlciwgd3Q9KDEtcG93ZXIuZGF0YSRUKSpwb3dlci5kYXRhJGV0aDFfZXVyKQp3aGl0ZS5xdGU9cS50cnQtcS5jb250cm9sCiNwbG90KGMoMC4wNSwwLjEsIDAuMjUsIDAuNSwgMC43NSwgMC45MCwgMC45NSksd2hpdGUucXRlLHR5cGU9ImIiKQoKcS50cnQ9cXVhbnRpbGUodGF1cz10YXVzLCB5PXBvd2VyLmRhdGEkaGlzcC5wb3dlciwgd3Q9cG93ZXIuZGF0YSRUKnBvd2VyLmRhdGEkZXRoMV9oaXNwKQpxLmNvbnRyb2w9cXVhbnRpbGUodGF1cz10YXVzLCB5PXBvd2VyLmRhdGEkaGlzcC5wb3dlciwgd3Q9KDEtcG93ZXIuZGF0YSRUKSpwb3dlci5kYXRhJGV0aDFfaGlzcCkKaGlzcC5xdGU9cS50cnQtcS5jb250cm9sCiNwbG90KGMoMC4wNSwwLjEsIDAuMjUsIDAuNSwgMC43NSwgMC45MCwgMC45NSksaGlzcC5xdGUsdHlwZT0iYiIpCgoKcS50cnQ9cXVhbnRpbGUodGF1cz10YXVzLCB5PXBvd2VyLmRhdGEkYXNpYW4ucG93ZXIsIHd0PXBvd2VyLmRhdGEkVCpwb3dlci5kYXRhJGV0aDFfZXNhKQpxLmNvbnRyb2w9cXVhbnRpbGUodGF1cz10YXVzLCB5PXBvd2VyLmRhdGEkYXNpYW4ucG93ZXIsIHd0PSgxLXBvd2VyLmRhdGEkVCkqcG93ZXIuZGF0YSRldGgxX2VzYSkKYXNpYW4ucXRlPXEudHJ0LXEuY29udHJvbAojcGxvdChjKDAuMDUsMC4xLCAwLjI1LCAwLjUsIDAuNzUsIDAuOTAsIDAuOTUpLGFzaWFuLnF0ZSx0eXBlPSJiIikKCmRhdGEuZnJhbWUocT1yZXAoYygwLjA1LDAuMSwgMC4yNSwgMC41LCAwLjc1LCAwLjkwLCAwLjk1KSw0KSxxdGU9YyhibGFjay5xdGUsd2hpdGUucXRlLGhpc3AucXRlLGFzaWFuLnF0ZSkscmFjZT1yZXAoYygiQmxhY2siLCJXaGl0ZSIsIkhpc3BhbmljIiwiQXNpYW4iKSxlYWNoPTcpKSU+JQogIGdncGxvdChhZXMoeD1xLHk9cXRlLGNvbD1yYWNlKSkrCiAgZ2VvbV9wb2ludCgpKwogIGdlb21fbGluZSgpKwogIHNjYWxlX2NvbG9yX3N0YXJ0cmVrKCkKCmBgYAoK